﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Psl.Controls;
using System.Windows.Forms;
using Psl.Chat;

namespace Stl.Chat.Components
{
    public partial class ChatBridge : Component
    {
        protected DesignFrame designFrame;
        protected IChat model;
        protected string userID;
        // l'indice de message à récupérer dans le model
        protected int curMsgIdx = 0;
        // je stocke les deux dernieres actions, car de le cas d'add control
        // designframe selectionne le control juste apres la creation du control
        protected DesignAction[] lastActions = new DesignAction[2];

        public ChatBridge()
        {
            InitializeComponent();
        }

        public ChatBridge(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
        }

        public DesignFrame DesignFrame
        {
            get
            {
                return designFrame;
            }
            set
            {
                if (value == null)
                    return;

                if (designFrame != null)
                {
                    designFrame.ControlAdded -= DoControlAdded;
                    designFrame.ControlRemoved -= DoControlRemoved;
                    designFrame.SelectedControlChanged -= DoSelectedControlChanged;
                    designFrame.SelectedControlEndDrag -= DoSelectedControlEndDrag;
                    designFrame.MouseMove -= DoMouseMove;
                }

                designFrame = value;
                designFrame.ControlAdded += DoControlAdded;
                designFrame.ControlRemoved += DoControlRemoved;
                designFrame.SelectedControlChanged += DoSelectedControlChanged;
                designFrame.SelectedControlEndDrag += DoSelectedControlEndDrag;
                designFrame.MouseMove += DoMouseMove;
                // designFrame est enable seulement si ChatBridge est enable
                designFrame.Enabled = Enable;
            }
        }

        public bool Enable
        {
            get;
            set;
        }

        protected void DoControlAdded(object sender, ControlEventArgs e)
        {
            // Je parcours la liste des dernières actions recues,
            // Pour vérifier si l'action currente a déjà été traitée
            foreach (DesignAction lastAction in lastActions)
            {
                if (lastAction != null && (lastAction is DesignDrop))
                {
                    DesignDrop drop = (DesignDrop)lastAction;
                    Control c = e.Control;
                    if (drop.TypeName.Equals(c.GetType().AssemblyQualifiedName)
                        && drop.Name.Equals(c.Name)
                        && drop.X == c.Location.X
                        && drop.Y == c.Location.Y
                        && drop.Width == c.Size.Width
                        && drop.Height == c.Size.Height)
                        return;
                }
            }
            model.Add(userID, DesignDrop.Serialize(e.Control));
        }

        protected void DoControlRemoved(object sender, ControlEventArgs e)
        {
            Control c = e.Control;
            if (c == null)
                return;

            foreach (DesignAction lastAction in lastActions)
            {
                if (lastAction != null && (lastAction is DesignRemove))
                {
                    DesignRemove del = (DesignRemove)lastAction;
                    if (del.Name.Equals(c.Name))
                        return;
                }
            }
            model.Add(userID, DesignRemove.Serialize(c));
        }

        protected void DoSelectedControlChanged(object sender, EventArgs e)
        {
            Control c = DesignFrame.SelectedControl;
            if (c == null)
                return;

            foreach (DesignAction lastAction in lastActions)
            {
                if (lastAction != null && (lastAction is DesignSelect))
                {
                    DesignSelect select = (DesignSelect)lastAction;
                    if (select.Name.Equals(c.Name))
                        return;
                }
            }
            model.Add(userID, DesignSelect.Serialize(DesignFrame.SelectedControl));
        }

        protected void DoSelectedControlEndDrag(object sender, EventArgs e)
        {
            Control c = DesignFrame.SelectedControl;
            if (c == null)
                return;

            foreach (DesignAction lastAction in lastActions)
            {
                if (lastAction != null && (lastAction is DesignDrag))
                {
                    DesignDrag drag = (DesignDrag)lastAction;
                    if (drag.Name.Equals(c.Name)
                        && drag.X == c.Location.X
                        && drag.Y == c.Location.Y
                        && drag.Width == c.Size.Width
                        && drag.Height == c.Size.Height)
                        return;
                }
            }
            model.Add(userID, DesignDrag.Serialize(DesignFrame.SelectedControl));
        }

        protected void DoMouseMove(object sender, MouseEventArgs e)
        {
            if (!DesignFrame.IsDragging)
                return;
            model.Add(userID, DesignDrag.Serialize(DesignFrame.SelectedControl));
        }

        private void chatEvents_ChatChanged(object sender, Psl.Chat.ChatChangedEventArgs e)
        {
            if (!this.Enable || DesignFrame == null)
                return;
            ChatItem[] items = model.GetLasts(curMsgIdx);
            curMsgIdx += items.Length;
            string[] strs;
            string action;
            bool res;
            foreach (ChatItem item in items)
            {
                if (userID.Equals(item.UserID))
                    continue;

                strs = item.Text.Split(DesignAction.Delimiter);
                if (strs.Length < 3)
                    continue;
                if (!DesignAction.Graphics.Equals(strs[0]))
                    continue;
                action = strs[1];
                if ("ControlAdd".Equals(action))
                {
                    DesignDrop drop = new DesignDrop();
                    drop.Deserialize(strs);
                    lastActions[0] = lastActions[1];
                    lastActions[1] = drop;
                    drop.Action(designFrame);
                }
                else if ("ControlRemove".Equals(action))
                {
                    DesignRemove del = new DesignRemove();
                    del.Deserialize(strs);
                    lastActions[0] = lastActions[1];
                    lastActions[1] = del;
                    del.Action(designFrame);
                }
                else if ("ControlSelect".Equals(action))
                {
                    DesignSelect select = new DesignSelect();
                    select.Deserialize(strs);
                    lastActions[0] = lastActions[1];
                    lastActions[1] = select;
                    select.Action(designFrame);
                }
                else if ("ControlDrag".Equals(action))
                {
                    DesignDrag drag = new DesignDrag();
                    drag.Deserialize(strs);
                    lastActions[0] = lastActions[1];
                    lastActions[1] = drag;
                    drag.Action(designFrame);
                }
                else
                    continue;
            }
        }

        private void chatEvents_ChatOpened(object sender, EventArgs e)
        {
            model = ChatRegistry.ChatState.ModelInternal;
            userID = model.GetNewUserID();
            curMsgIdx = 0;
            this.Enable = true;
            DesignFrame.Enabled = true;
        }

        private void chatEvents_ChatClosing(object sender, EventArgs e)
        {
            this.Enable = false;
            DesignFrame.Enabled = false;
        }
    }
}
